import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { ElMessage } from "element-plus";
import { merge } from "lodash-es";

export interface IPage<T> {
  total: number;
  data: T;
}

export class Request {
  instance: AxiosInstance;
  baseConfig = {
    headers: {
      "Content-Type": "application/json",
    },
    timeout: 10000,
    data: {},
  };

  constructor(config: Partial<AxiosRequestConfig>) {
    this.instance = axios.create(merge(this.baseConfig, config));
    this.instance.interceptors.request.use(
      (config) => {
        return config;
      },
      (err) => {
        return Promise.reject(err);
      }
    );
    this.instance.interceptors.response.use(
      (response) => {
        // apiData 是 API 返回的数据
        const data = response.data;
        // 这个 Code 是和后端约定的业务 Code
        const code = data.code;
        // 如果没有 Code, 代表这不是项目后端开发的 API
        if (code === undefined) {
          ElMessage.error("非本系统的接口");
          return Promise.reject(new Error("非本系统的接口"));
        } else {
          switch (code) {
            case 0:
              // code === 0 代表没有错误
              return data.data;
            default:
              // 不是正确的 Code
              ElMessage.error(data.msg || "Error");
              return Promise.reject(new Error("Error"));
          }
        }
      },
      (err) => {
        let message = "";
        switch (err.response.status) {
          case 400:
            message = "请求错误(400)";
            break;
          case 401:
            message = "未授权，请重新登录(401)";
            // 这里可以做清空storage并跳转到登录页的操作
            break;
          case 403:
            message = "拒绝访问(403)";
            break;
          case 404:
            message = "请求出错(404)";
            break;
          case 408:
            message = "请求超时(408)";
            break;
          case 500:
            message = "服务器错误(500)";
            break;
          case 501:
            message = "服务未实现(501)";
            break;
          case 502:
            message = "网络错误(502)";
            break;
          case 503:
            message = "服务不可用(503)";
            break;
          case 504:
            message = "网络超时(504)";
            break;
          case 505:
            message = "HTTP版本不受支持(505)";
            break;
          default:
            message = `连接出错(${err.response.status})!`;
        }
        // 这里错误消息可以使用全局弹框展示出来
        // 比如element plus 可以使用 ElMessage
        ElMessage({
          showClose: true,
          message: `${message}，请检查网络或联系管理员！`,
          type: "error",
        });
        // 这里是AxiosError类型，所以一般我们只reject我们需要的响应即可
        return Promise.reject(err.response);
      }
    );
  }

  request<T>(config: Partial<AxiosRequestConfig>): Promise<T> {
    return this.instance.request(config);
  }
}
